/**
 * @Company: 北京慧点科技有限公司 | www.smartdot.com.cn
 * @Copyright 1998-2020 © Smartdot Technologies Co., Ltd.
 */
package feizhou.untils.tools.http;

import feizhou.untils.tools.http.bean.FileInfo;
import feizhou.untils.tools.io.IOStreamUtil;
import feizhou.untils.tools.json.JSONUtil;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * http请求工具类
 *
 * @author <a href="920786312@qq.com">周飞</a>
 * @since 2023/8/15 16:51
 */
public class HttpUtils {

    static Logger logger = LoggerFactory.getLogger(HttpUtils.class);
    private static String HTTP_CONTENT_CHARSET = "UTF-8";// 编码

    private static int connectTimeout = 5000; // 连接超时5秒
    private static int connectionRequestTimeout = 1000; // 连接请求超时5秒
    private static int readTimeout = 30000; // 默认读取超时30秒
    private static int socketTimeout = 5000;//表示socket 发送和接收端 单次数据传输超过5s 就会进行中断，如果每4900ms都有一个数据包交互，那就会一直连接不断
    private static Map<String, String> defaultHeaderMap = new HashMap<>(); // 默认头部参数配置
    private static RequestConfig defaultRequestConfig = null; // 默认请求配置

    static {
        defaultHeaderMap.put("Content-Type", "application/json");
        defaultRequestConfig = RequestConfig.custom()
                .setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .setSocketTimeout(socketTimeout).build();
    }

    /**
     * GET请求
     *
     * @param url        请求的url
     * @param parameters 请求的参数
     * @param headerMap  头部请求，可以不传，使用默认配置
     * @return java.lang.String
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/16 11:35
     */
    public static String get(String url, Map<String, String> parameters, Map<String, String> headerMap, RequestConfig requestConfig) {
        String result = null;
        // GET请求
        HttpGet httpGet = null;
        try {
            URIBuilder uriBuilder = new URIBuilder(url);

            // 设置参数
            if (parameters != null && parameters.size() > 0) {
                //使用列表来保存参数
                List<NameValuePair> nameValuePairs = new LinkedList<NameValuePair>();
                for (Map.Entry<String, String> entry : parameters.entrySet()) {
                    BasicNameValuePair nameValuePair = new BasicNameValuePair(entry.getKey(), entry.getValue());
                    nameValuePairs.add(nameValuePair);
                }
                //设置参数
                uriBuilder.setParameters(nameValuePairs);
            }
            // GET请求
            httpGet = new HttpGet(uriBuilder.build());

            result = httpClientExecute(httpGet, headerMap, requestConfig);
        } catch (URISyntaxException e) {
            logger.error("URI解析异常，请求地址失败 ： " + url);
            e.printStackTrace();
        } catch (ParseException e) {
            logger.error("解析错误，请求地址失败!");
            e.printStackTrace();
        } finally {
            if (null != httpGet) {
                httpGet.releaseConnection();
            }
        }
        return result;
    }

    /**
     * POST请求
     *
     * @param parameters    请求的参数
     * @param url           请求的url
     * @param requestConfig 请求配置，可以不传，使用默认配置
     * @param headerMap     头部请求，可以不传，使用默认配置
     * @return java.lang.String
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/16 14:24
     */
    public static String post(String url, Map<String, Object> parameters, Map<String, String> headerMap, RequestConfig requestConfig) {
        String jsonParameters = null;
        if (parameters != null && parameters.size() > 0) {
            jsonParameters = JSONUtil.toJsonStr(parameters);
        }
        return post(url, jsonParameters, headerMap, requestConfig);
    }

    /**
     * POST请求
     *
     * @param jsonParameters body的json字符串
     * @param url            请求的url
     * @param requestConfig  请求配置，可以不传，使用默认配置
     * @param headerMap      头部请求，可以不传，使用默认配置
     * @return java.lang.String
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/16 14:23
     */
    public static String post(String url, String jsonParameters, Map<String, String> headerMap, RequestConfig requestConfig) {
        String result = null;
        // POST请求
        HttpPost httpPost = null;
        try {
            httpPost = new HttpPost(url);
            // 设置参数
            StringEntity stringEntity = new StringEntity(jsonParameters, ContentType.create("text/json", "UTF-8"));
            httpPost.setEntity(stringEntity);
            if (headerMap == null) {
                //使用默认的头部
                headerMap = defaultHeaderMap;
            }
            result = httpClientExecute(httpPost, headerMap, requestConfig);
        } catch (ParseException e) {
            logger.error("解析错误，请求失败!");
            e.printStackTrace();
        } finally {
            if (null != httpPost) {
                httpPost.releaseConnection();
            }
        }
        return result;
    }

    /**
     * 执行http客户端请求
     *
     * @param request       请求
     * @param headerMap     头部请求
     * @param requestConfig 请求配置
     * @return java.lang.String
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/16 14:14
     */
    public static String httpClientExecute(final HttpUriRequest request, Map<String, String> headerMap, RequestConfig requestConfig) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;

        //使用默认的头部
        if (headerMap == null) {
            headerMap = defaultHeaderMap;
        }
        //使用默认的请求配置
        if (requestConfig == null) {
            requestConfig = defaultRequestConfig;
        }

        //设置请求配置
        if (request instanceof HttpGet) {
            ((HttpGet) request).setConfig(requestConfig);
        } else if (request instanceof HttpPost) {
            ((HttpPost) request).setConfig(requestConfig);
        }

        //设置头部属性
        if (headerMap != null) {
            Set<Map.Entry<String, String>> entries = headerMap.entrySet();
            entries.stream().forEach(e -> request.addHeader(e.getKey(), e.getValue().toString()));
        }

        try {
            response = httpClient.execute(request);

            //获取状态码
            int statusCode = response.getStatusLine().getStatusCode();
            if (HttpStatus.SC_OK != statusCode) {
                logger.error("请求地址失败！错误代码：" + response.getStatusLine().toString());
            }

            String result = EntityUtils.toString(response.getEntity(), "utf-8");
            EntityUtils.consume(response.getEntity());
            return result;
        } catch (ClientProtocolException e) {
            logger.error("Http协议出现问题，请求失败!");
            e.printStackTrace();
        } catch (IOException e) {
            logger.error("IO异常，请求失败!");
            e.printStackTrace();
        } finally {
            // 释放连接
            try {
                if (null != response) {

                    //确保流内容，已经完全读取完毕
                    EntityUtils.consume(response.getEntity());
                    response.close();
                }
                if (null != httpClient) {
                    httpClient.close();
                }
            } catch (IOException e) {
                logger.error("释放连接出错!");
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 发送附件
     *
     * @param url
     * @param files
     * @return java.lang.String
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/30 16:15
     */
    public static String postSendFiles(String url, List<MultipartFile> files, Map<String, String> parameters,Map<String, String> headerMap,  String binaryBodyKey) {
        String result = null;

        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            HttpPost httpPost = new HttpPost(url);
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();


            //构建附件body
            for (MultipartFile file : files) {
                String filename = file.getOriginalFilename();
                builder.addBinaryBody(binaryBodyKey, file.getBytes(), ContentType.MULTIPART_FORM_DATA, filename);
            }

            //扩展参数
            if (parameters != null && parameters.size() > 0) {
                parameters.entrySet().forEach(e -> {
                    builder.addPart(e.getKey(), new StringBody(e.getValue(), ContentType.TEXT_PLAIN));
                });
            }
            //设置头部属性
            if (headerMap != null) {
                Set<Map.Entry<String, String>> entries = headerMap.entrySet();
                for (Map.Entry<String, String> entry : entries) {
                    httpPost.addHeader(entry.getKey(), entry.getValue().toString());
                }
            }
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);
            CloseableHttpResponse response = httpClient.execute(httpPost);
            result = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * GET 下载附件
     *
     * @param url        请求的url
     * @param parameters 请求的参数
     * @param headerMap  头部请求，可以不传，使用默认配置
     * @return java.lang.String
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/16 11:35
     */
    public static FileInfo getDownloadFile(String url, Map<String, String> parameters, Map<String, String> headerMap, RequestConfig requestConfig) {

        //字节流
        InputStream inputStream = null;
        //构建附件信息
        FileInfo fileInfo = FileInfo.build();
        // GET请求
        HttpGet httpGet = null;
        try {
            URIBuilder uriBuilder = new URIBuilder(url);

            // 设置参数
            if (parameters != null && parameters.size() > 0) {
                //使用列表来保存参数
                List<NameValuePair> nameValuePairs = new LinkedList<NameValuePair>();
                for (Map.Entry<String, String> entry : parameters.entrySet()) {
                    BasicNameValuePair nameValuePair = new BasicNameValuePair(entry.getKey(), entry.getValue());
                    nameValuePairs.add(nameValuePair);
                }
                //设置参数
                uriBuilder.setParameters(nameValuePairs);
            }
            // GET请求
            httpGet = new HttpGet(uriBuilder.build());

            //设置头部属性
            if (headerMap != null) {
                Set<Map.Entry<String, String>> entries = headerMap.entrySet();
                for (Map.Entry<String, String> entry : entries) {
                    httpGet.addHeader(entry.getKey(), entry.getValue().toString());
                }
            }
            CloseableHttpClient httpClient = HttpClients.createDefault();
            CloseableHttpResponse response = httpClient.execute(httpGet);


            // 获取附件名称
            Header[] headers = response.getHeaders("content-disposition");
            if (headers != null && headers.length > 0) {
                //attachment;fileName=3166675354999906884.zip
                String fileName = headers[0].getValue();
                int index = fileName.lastIndexOf("fileName=");
                if (index != -1) {//有附件名称
                    fileName = fileName.substring(index + 9);
                    fileInfo.setName(fileName);
                }
            }

            HttpEntity entity = response.getEntity();
            //获取输入流
            inputStream = entity.getContent();
            byte[] data = IOStreamUtil.toBytes(inputStream);
            fileInfo.setContent(data);

        } catch (URISyntaxException e) {
            logger.error("URI解析异常，请求地址失败 ： " + url);
            e.printStackTrace();
        } catch (IOException e) {
            logger.error("IO异常，返回数据有问题!");
            e.printStackTrace();
        } catch (ParseException e) {
            logger.error("解析错误，请求地址失败!");
            e.printStackTrace();
        } finally {
            if (null != httpGet) {
                httpGet.releaseConnection();
            }
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return fileInfo;
    }


    public static void main(String[] args) throws Exception {
        // System.out.println(sendGet("http://openapi.ngrok.cc/v20/events.json?page_index=1&page_size=10",
        // null,
        // mofangHeads));
//        long start = System.currentTimeMillis();
//        System.out.println(sendGet("http://www.baidu.com", null, null));
//        System.out.println(System.currentTimeMillis() - start);
//    	for(int i=0;i<1;i++){
//    		String res=sendPostBaidu("http://data.zz.baidu.com/urls?site=www.2bulu.com&token=nhju6YaZ7VKrp9AR", Arrays.asList("http://www.2bulu.com/event/event_discription.htm?pageNumber=1&id=35989","http://www.2bulu.com/event/event_discription.htm?pageNumber=1&id=35990"));
//    		try {
//    			BaiduRes br=JsonUtil.getObjectMapper().readValue(res, BaiduRes.class);
//    			System.out.println(br);
//    		} catch (Exception e) {
//    			e.printStackTrace();
//    		}
//    	}
//        String urlString = "http://172.18.94.94:8080/api/oct_oa/departToDmpDepart";
//        Map<String, String> parameters = new HashMap<>();
//        parameters.put("userId", "1");
//        String jsonParameters = "[{\"id\":1,\"text\":\"测试1\",\"parentId\":0,\"sortOrder\":1},{\"id\":2,\"text\":\"测试2\",\"parentId\":0,\"sortOrder\":1}]";
//        String s = post(urlString, jsonParameters, null, null);
//        System.out.println("s:" + s);
//
//        String url = "http://172.18.94.94:8080/api/oct_oa/attachment/0/1711222079156453377";
//        String filePath = "C:\\Users\\26372\\Desktop\\temp\\1.png";
//        String filePath2 = "C:\\Users\\26372\\Desktop\\temp\\2.png";
//        List<MultipartFile> list = new ArrayList<>();
//        MultipartFile multipartFile = IOStreamUtil.toMultipartFile(new FileInputStream(filePath), "1.png");
//        MultipartFile multipartFile2 = IOStreamUtil.toMultipartFile(new FileInputStream(filePath2), "2.png");
//        list.add(multipartFile);
//        list.add(multipartFile2);
//        postFiles(url, list, null, "file");


    }
}